import ccxt.pro as ccxt
from loguru import logger
import asyncio
from typing import Dict, Optional
from logs import setup_exchange_logger
import os
from dotenv import load_dotenv

# import ccxt.pro as ccxtpro
# print('CCXT version', ccxtpro.__version__)
# print('Supported exchanges:', ccxtpro.exchanges)

# 加载.env文件
load_dotenv()

class ExchangeManager:
    """
    交易所管理器
    负责管理交易所实例的生命周期和基础配置
    """
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(ExchangeManager, cls).__new__(cls)
        return cls._instance
    
    def __init__(self):
        # 如果已经初始化过，直接返回
        if hasattr(self, 'initialized') and self.initialized:
            return
            
        self.exchanges: Dict[str, ccxt.Exchange] = {}
        self.logger = setup_exchange_logger()
        self.initialized = False
        
        # 基础配置
        self.options = {
            'enableRateLimit': True,
            'options': {
                'defaultType': 'swap',
            }
        }
        
        # 支持的交易所列表
        self.supported_exchanges = ['gateio', 'xt', 'bitget']
        
        # 创建交易所实例
        self._create_exchanges()
        
    def _create_exchanges(self):
        """创建交易所实例"""
        self.logger.info("开始创建交易所实例...")
        
        for exchange_id in self.supported_exchanges:
            try:
                exchange_class = getattr(ccxt, exchange_id)
                self.exchanges[exchange_id] = exchange_class(self.options)
                # self.logger.info(f"{exchange_id} 交易所实例创建成功")
            except Exception as e:
                self.logger.error(f"创建 {exchange_id} 交易所实例失败: {str(e)}")
                # 继续创建其他交易所实例
                
        if not self.exchanges:
            self.logger.error("没有成功创建任何交易所实例")
            raise Exception("交易所初始化失败")
            
        self.logger.info(f"成功创建 {len(self.exchanges)} 个交易所实例")

    async def load_markets(self, exchange_id: str, max_retries: int = 3) -> bool:
        """加载交易所市场数据"""
        exchange = self.get_exchange(exchange_id)
        if not exchange:
            self.logger.error(f"交易所 {exchange_id} 不存在")
            return False
            
        for attempt in range(max_retries):
            try:
                await exchange.load_markets()
                # self.logger.info(f"{exchange_id} 市场数据加载成功")
                return True
            except Exception as e:
                if attempt == max_retries - 1:
                    self.logger.error(f"{exchange_id} 加载市场数据失败: {str(e)}")
                    raise
                self.logger.warning(f"{exchange_id} 第{attempt + 1}次加载失败，3秒后重试...")
                await asyncio.sleep(3)
        
        return False
        
    async def load_all_markets(self) -> bool:
        """加载所有交易所的市场数据"""
        if not self.exchanges:
            self.logger.error("没有可用的交易所实例")
            return False
            
        self.logger.info("开始加载所有交易所的市场数据...")
        
        tasks = [self.load_markets(exchange_id) for exchange_id in self.exchanges]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # 检查结果
        failed_exchanges = []
        for exchange_id, result in zip(self.exchanges.keys(), results):
            if isinstance(result, Exception):
                failed_exchanges.append(exchange_id)
                self.logger.error(f"{exchange_id} 加载市场数据失败: {str(result)}")
        
        if failed_exchanges:
            self.logger.error(f"以下交易所加载市场数据失败: {', '.join(failed_exchanges)}")
            return False
            
        self.initialized = True
        self.logger.info("所有交易所市场数据加载成功")
        return True

    def get_exchange(self, exchange_id: str) -> Optional[ccxt.Exchange]:
        """获取交易所实例"""
        return self.exchanges.get(exchange_id)

    def get_all_exchanges(self) -> Dict[str, ccxt.Exchange]:
        """获取所有交易所实例"""
        return self.exchanges
        
    def init_private_api(self, exchange_id: str, api_key: Optional[str] = None, secret_key: Optional[str] = None, password: Optional[str] = None) -> bool:
        """
        初始化交易所的私有API
        
        Args:
            exchange_id: 交易所ID
            api_key: API密钥（可选，如果不提供则从.env文件获取）
            secret_key: 密钥（可选，如果不提供则从.env文件获取）
            password: 密码（可选，如果不提供则从.env文件获取）
            
        Returns:
            bool: 是否成功初始化
        """
        try:
            exchange = self.get_exchange(exchange_id)
            if not exchange:
                self.logger.error(f"交易所 {exchange_id} 不存在")
                return False

            # 从参数或.env文件获取API密钥
            api_key = api_key or os.getenv(f"{exchange_id.upper()}_API_KEY")
            secret_key = secret_key or os.getenv(f"{exchange_id.upper()}_SECRET")
            password = password or os.getenv(f"{exchange_id.upper()}_PASSWORD")
            
            # 检查是否获取到API密钥
            if not api_key or not secret_key:
                self.logger.error(f"无法获取 {exchange_id} 的API密钥，请检查.env文件或提供参数")
                return False

            # 设置API密钥
            exchange.apiKey = api_key
            exchange.secret = secret_key
            
            # 如果提供了password（某些交易所需要），则设置
            if password:
                exchange.password = password

            self.logger.info(f"交易所 {exchange_id} 私有API初始化成功")
            return True

        except Exception as e:
            self.logger.error(f"初始化交易所 {exchange_id} 私有API失败: {str(e)}")
            return False
            
    def init_all_private_apis(self) -> bool:
        """
        初始化所有交易所的私有API
        
        Returns:
            bool: 是否全部成功初始化
        """
        success = True
        for exchange_id in self.exchanges:
            if not self.init_private_api(exchange_id):
                success = False
                self.logger.error(f"{exchange_id} 私有API初始化失败")
        
        return success

    async def close_all_exchanges(self):
        """关闭所有交易所连接"""
        for exchange_id, exchange in self.exchanges.items():
            try:
                await exchange.close()
                self.logger.info(f"{exchange_id} 已关闭")
            except Exception as e:
                self.logger.error(f"关闭 {exchange_id} 失败: {str(e)}")
        
        self.exchanges.clear()
        self.initialized = False



#填充key
# 方式1：使用环境变量中的配置
# exchange_manager.init_private_api('gateio')  # 自动从.env文件获取配置

# # 方式2：手动提供配置
# exchange_manager.init_private_api('gateio', 'your_api_key', 'your_secret_key', 'your_password')

# # 方式3：初始化所有交易所
# exchange_manager.init_all_private_apis()  # 自动初始化所有交易所


